#include <boost/date_time/posix_time/posix_time.hpp>
#include "../Graphics/Presentation.h"
#include "./MainLoop.h"

using namespace GameLogic;

/* Docelowy czas trwania pojedynczej klatki w milisekundach. */
#define NOMINAL_STEP 33

MainLoop::MainLoop( Simulation* simulation, bool is_server ):
	simulation_( simulation ),
	presentation_( Graphics::Presentation::getInstance() ),
	is_server_( is_server ),
	state_( Core::GameState::StateMachine::getInstance().getState() )
{
	Core::GameState::StateMachine::getInstance().addGameStateChangeListener( this );
}

MainLoop::~MainLoop() {}

void MainLoop::notifyGameStateChange( Core::GameState::States state ) {
	state_ = state;
}

void MainLoop::enterMainGameLoop() {

	bool do_loop = true;

	boost::posix_time::ptime previous_time = boost::posix_time::microsec_clock::local_time();

	while( do_loop ) {

		/* SEKCJA 0 - przepompowuje zdarzenia */

		Ogre::WindowEventUtilities::messagePump();

		/* SEKCJA I - obliczanie kroku czasu */

		//oblicza czas, ktory uplynal od przetworzenia ostatniej klatki
		boost::posix_time::ptime current_time = boost::posix_time::microsec_clock::local_time();
		boost::posix_time::time_duration time_delta( current_time - previous_time );
		previous_time = current_time;

		//krok symulacji (w milisekundach)
		long time_quantum = time_delta.total_milliseconds();

		/* FPS'y: */
		//ttm += time_quantum;
		//fct += 1;
		//float fps = (static_cast<float>(fct) / static_cast<float>(ttm)) * 1000.0f;

		/* SEKCJA II - logika i rysowanie: */

		switch( state_ ) {
		case Core::GameState::gsIngame:
			// rozgrywka trwa:
			simulation_->simulate( time_quantum );
			presentation_.render( time_quantum );
			break;
		case Core::GameState::gsSetup:
			// ladowanie stanu nadsylanego przez serwer:
			//TODO: spanko
			simulation_->receiveCommands();
			break;
		default:
			do_loop = false;
		}

		/* SEKCJA III - zwalnianie procesora */

		//Usypianie watku:
		boost::posix_time::ptime finished_time = boost::posix_time::microsec_clock::local_time();
		boost::posix_time::time_duration processing_duration( finished_time - current_time );
		long sleep_time = NOMINAL_STEP - processing_duration.total_milliseconds();
		if( sleep_time >= 1 ) {
			boost::posix_time::time_duration td =
				boost::posix_time::milliseconds( sleep_time );
			boost::this_thread::sleep( td );
		}
	}



}
